using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Storage;
using System.Diagnostics;

namespace UWBGL_XNA_Lib10
{
	//This is our custome vertex structure XNA likes to recieve 
	//arrays of structs with vertex information. For simple, unlit
	//drawing; a vertex and color at the vertex will suffice.
	public struct DeviceVertexFormat
	{
		private Vector3 m_Position;
		private Color m_Color;

		//Format in which this type of vertex will be passed to the graphics hardware
		public static VertexElement[] VertexElements =
        {
            new VertexElement(0, 0, VertexElementFormat.Vector3, VertexElementMethod.Default, 
                              VertexElementUsage.Position, 0),
            new VertexElement(0, sizeof(float)*3, VertexElementFormat.Color, VertexElementMethod.Default, 
                              VertexElementUsage.Color, 0) 
        };

		//m_Position accessor and modifier
		public Vector3 Position
		{
			get
			{
				return m_Position;
			}
			set
			{
				m_Position = value;
			}
		}

		//m_Color accessor and modifier
		public Color Color
		{
			get
			{
				return m_Color;
			}
			set
			{
				m_Color = value;
			}
		}
	};

	public class UWB_XNAGraphicsSystem
	{
		private EffectPool m_EffectPool;
		private BasicEffect m_BasicEffect;
		private GraphicsDevice m_XNA_GraphicsDevice;
		public static UWB_XNAGraphicsSystem m_TheAPI = new UWB_XNAGraphicsSystem();

		private UWB_XNAGraphicsSystem()
		{
		}

		public bool CreateGraphicsContext(IntPtr hwnd, ref PresentationParameters pp)
		{
			//define presentation parameters
			pp = new PresentationParameters();
			pp.BackBufferCount = 1;
			pp.BackBufferFormat = SurfaceFormat.Unknown;
			pp.DeviceWindowHandle = hwnd;
			pp.IsFullScreen = false;
			pp.SwapEffect = SwapEffect.Discard;
			pp.BackBufferHeight = Control.FromHandle(hwnd).Height;
			pp.BackBufferWidth = Control.FromHandle(hwnd).Width;

			if (m_XNA_GraphicsDevice != null)
				return false;
			//create an XNA graphics device
			m_XNA_GraphicsDevice = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware,
				hwnd, pp);

			//check if graphics device was created
			Debug.Assert(m_XNA_GraphicsDevice != null, "XNA Graphics Device did not Initialize");

			m_EffectPool = new EffectPool();
			m_BasicEffect = new BasicEffect(m_XNA_GraphicsDevice, m_EffectPool);

			//set the model matrix to identity
			m_BasicEffect.World = Matrix.Identity;
			m_BasicEffect.View = Matrix.Identity;
			m_BasicEffect.Projection = Matrix.Identity;

			return true;
		}

		public GraphicsDevice GetActiveDevice()
		{
			return m_XNA_GraphicsDevice;
		}

		public bool BeginScene(PresentationParameters pp)
		{
			if (m_XNA_GraphicsDevice == null)
				return false;
			m_XNA_GraphicsDevice.Reset(pp);
			m_XNA_GraphicsDevice.VertexDeclaration = new VertexDeclaration(m_XNA_GraphicsDevice, DeviceVertexFormat.VertexElements);
			m_XNA_GraphicsDevice.RenderState.CullMode = CullMode.None;
			m_XNA_GraphicsDevice.RenderState.FillMode = FillMode.Solid;
			m_XNA_GraphicsDevice.Clear(new Color(new Vector4(.8f, .8f, .8f, 0)));

			m_BasicEffect.VertexColorEnabled = true;

			m_BasicEffect.Begin();
			m_BasicEffect.CurrentTechnique.Passes[0].Begin();

			return true;
		}

		public bool EndSceneAndShow(PresentationParameters pp)
		{
			if (m_XNA_GraphicsDevice == null)
				return false;

			m_BasicEffect.CurrentTechnique.Passes[0].End();
			m_BasicEffect.End();
			m_XNA_GraphicsDevice.Present();

			return true;
		}

		public void setViewMatrix(Matrix matrix)
		{
			m_BasicEffect.View = matrix;
			m_BasicEffect.CommitChanges();
		}

		public void setWorldMatrix(Matrix matrix)
		{
			m_BasicEffect.World = matrix;
			m_BasicEffect.CommitChanges();
		}
	}
}